//
// Created on 2024/1/22.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "headers/napi_utils.h"
#include "Log.h"
#include <cstdlib>
#include <cstring>

napi_value napiUtils::loadNapiArgs(napi_env env, napi_callback_info info) {
    napi_value args[1] = {0};
    size_t argc = 1;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return nullptr;
    }
    return args[0];
}


napi_value napiUtils::createStringNapi(napi_env env, const char *value) {
    // napi_value 转换int类型
    if (value == nullptr) {
        return nullptr;
    }
    napi_value result = nullptr;
    if (napi_create_string_utf8(env, value, strlen(value), &result) != napi_ok) {
        return nullptr;
    }
    return result;
}


napi_value napiUtils::createIntNapi(napi_env env, int32_t value) {
    napi_value result = nullptr;
    if (napi_create_int32(env, value, &result) != napi_ok) {
        return nullptr;
    }
    return result;
}
napi_value napiUtils::createLongNapi(napi_env env, int64_t value) {
    napi_value result = nullptr;
    if (napi_create_int64(env, value, &result) != napi_ok) {
        return nullptr;
    }
    return result;
}

napi_value napiUtils::createDoubleNapi(napi_env env, double value) {
    napi_value result = nullptr;
    if (napi_create_double(env, value, &result) != napi_ok) {
        return nullptr;
    }
    return result;
}

napi_value napiUtils::createArrayNapi(napi_env env, int length) {
    napi_value result = nullptr;
    if (napi_create_array_with_length(env, length, &result) != napi_ok) {
        return nullptr;
    }
    return result;
}

napi_value napiUtils::createArrayNapi(napi_env env) {
    napi_value result = nullptr;
    if (napi_create_array(env, &result) != napi_ok) {
        return nullptr;
    }
    return result;
}

char *napiUtils::loadNapiString(napi_env env, napi_value value) {
    // napi_value 转换int类型
    char *str = nullptr;
    size_t typeLen = 0;
    // 主要作用是通过缓存复制的方法，将对象转换为char，复制到缓存中，获取长度
    if (napi_get_value_string_utf8(env, value, nullptr, 0, &typeLen) != napi_ok) {
        return nullptr;
    }
    str = new char[typeLen + 1];
    // 获取输入的字符串转换为char类型的str
    if (napi_get_value_string_utf8(env, value, str, typeLen + 1, &typeLen) != napi_ok) {
        delete[] str;
        return nullptr;
    }
    return str;
}

bool napiUtils::loadNapiInt(napi_env env, napi_value value, int32_t* data) {
    // napi_value 转换int类型
    if (napi_get_value_int32(env, value, data) != napi_ok) {
        return false;
    }
    return true;
}

bool napiUtils::loadNapiDouble(napi_env env, napi_value value, double_t* data) {
    // napi_value 转换int类型
    if (napi_get_value_double(env, value, data) != napi_ok) {
        return false;
    }
    return true;
}

bool napiUtils::loadNapiLong(napi_env env, napi_value value, int64_t* data) {
    // napi_value 转换int类型
    if (napi_get_value_int64(env, value, data) != napi_ok) {
        return false;
    }
    return true;
}


napi_ref napiUtils::loadNapiRef(napi_env env, napi_value value) {
    if (!value || !env) {
        return nullptr;
    }
    napi_ref result;
    if (napi_create_reference(env, value, 1, &result) != napi_ok) {
        napi_delete_reference(env, result);
        return nullptr;
    };
    return result;
}

napi_value napiUtils::createUint8Array(napi_env env, uint8_t *bytes, int size) {
    if (!env) {
        return nullptr;
    }
    // 创建 Uint8Array
    napi_value arrayBuffer;
    void *bufferData = nullptr;
    if (napi_create_arraybuffer(env, size, &bufferData, &arrayBuffer) != napi_ok) {
        return nullptr;
    }
    // 复制数据到arraybuffer
    std::memcpy(bufferData, bytes, size);
    napi_value typedArray;
    // 创建 Uint8Array 并绑定到 ArrayBuffer
    if (napi_create_typedarray(env, napi_uint8_array, size, arrayBuffer, 0, &typedArray) != napi_ok) {
        return nullptr;
    };
    return typedArray;
}

char *napiUtils::readRawFileContent(NativeResourceManager *manager, const char *path) {
    // 获取对应的rawDir指针对象
    RawFile64 *rawFile = OH_ResourceManager_OpenRawFile64(manager, path);
    if (rawFile == nullptr) {
        LOG_E("没有设置资源文件信息");
        return nullptr;
    }
    int size = OH_ResourceManager_GetRawFileSize64(rawFile);
    if (size <= 0) {
        LOG_E("文件长度为0");
        OH_ResourceManager_CloseRawFile64(rawFile);
        return nullptr;
    }
    LOG_E("size:%{public}d", size);
    // 获取rawfile大小并申请内存
    // 读取的数据缓存
    char *buffers = new char[size + 1];
    memset(buffers, 0, size + 1);
    try {
        long currentOffset = 0;
        int itemReadSize = 1024 * 10;
        while (true) {
            int64_t remainLen = size - currentOffset;
            LOG_E("remainLen:%ld", remainLen);
            if (remainLen <= 0) {
                break;
            }
            int64_t readLen;
            if (remainLen > itemReadSize) {
                readLen = OH_ResourceManager_ReadRawFile64(rawFile, buffers + currentOffset, itemReadSize);
            } else {
                readLen = OH_ResourceManager_ReadRawFile64(rawFile, buffers + currentOffset, remainLen);
            }
            if (readLen <= 0) {
                LOG_E("读取失败或文件结束，readLen: %ld", readLen);
                break;
            }
            LOG_I("读取的长度:%ld", readLen);
            currentOffset += readLen;
        }
    } catch (const std::bad_alloc &e) {
        LOG_E("Memory allocation failed: %s", e.what());
    }
    // 关闭打开的指针对象
    OH_ResourceManager_CloseRawFile64(rawFile);
    LOG_E("读取的数据是否为空:%{public}s", buffers);
    return buffers;
}

uint8_t *napiUtils::loadNapiUint8Arrays(napi_env env, napi_value value) {
    bool isArray;
    if (napi_is_arraybuffer(env, value, &isArray) != napi_ok || !isArray) {
        return nullptr;
    }

    void *data;
    size_t length;
    if (napi_get_arraybuffer_info(env, value, &data, &length) != napi_ok) {
        return nullptr;
    };
    return reinterpret_cast<uint8_t *>(data);
}

uint8_t *napiUtils::rotationAngle(uint8_t *inData, int width, int height, int orientation, int *isUseFree) {
    auto rotation = orientation % 360;
    if (rotation <= 0) {
        *isUseFree = 0;
        return inData;
    }
    *isUseFree = 1;
    LOG_I("当前需要旋转的角度为：%{public}d", rotation);
    LOG_I("对应需要设置的宽高为：%{public}d*%{public}d", width, height);
    int newWidth, newHeight;
    // 确定旋转后的宽高
    if (rotation == 90 || rotation == 270) {
        newWidth = height;
        newHeight = width;
    } else {
        newWidth = width;
        newHeight = height;
    }
    // 分配目标缓冲区
    uint8_t *outData = (uint8_t *)malloc(newWidth * newHeight * 3); // RGB每像素3字节
    // 遍历每个像素并重新映射
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            // 源像素位置
            int srcIndex = (y * width + x) * 3;
            // 目标像素位置
            int dstIndex;
            if (orientation == 90) {
                int newX = height - 1 - y;
                int newY = x;
                dstIndex = (newY * newWidth + newX) * 3;
            } else if (orientation == 180) {
                int newX = width - 1 - x;
                int newY = height - 1 - y;
                dstIndex = (newY * newWidth + newX) * 3;
            } else if (orientation == 270) {
                int newX = y;
                int newY = width - 1 - x;
                dstIndex = (newY * newWidth + newX) * 3;
            }

            // 拷贝像素数据 (R, G, B)
            memcpy(&outData[dstIndex], &inData[srcIndex], 3);
        }
    }
    return outData;
}